non local exitの実装
以下のRubyプログラムで、3行目のreturnはメソッドfooから抜ける
code:rb
def foo(ary)
ary.each do |x|
return if x
end
end
これの実装はけっこう面倒
CRubyではsetjmp/longjmpとかの劇物を使って実装している
というのはRubyには例外機構があるのでどのみち必要になるから
一方rurubyは関数の返り値を多値にすることで実装しているという話があった
Rustの関数が、「実際の値」と「returnした/breakした/raiseした」みたいな情報のunionを返すようになっている
この方式で大丈夫なのだろうか?
大丈夫でなさそうな例を考えた
Cで書かれたXMLパーサがあり、void each_node(root, コールバック関数) みたいなAPIがあるとする
このXMLパーサをrurubyから使うことを考える
Rustでラッパーを書く
code:rust
// なんかこういうのがあるとする(rurubyのソース見てないので想像)
enum RResult {
Normal(RValue),
Special(JumpType), // return/break/raise
}
extern "C" {
fn each_node(root: XMLNode, callback: ...);
}
fn ruruby_each_node(root: RValue, callback: RValue) -> RResult {
each_node(root, |c_node| {
let rresult = callback.as_block().call(c_node.into());
match rresult {
Normal(_) => (),
Special(_) => ここでruruby_each_nodeを抜けたいが、どうやって?
}
})
RResult::nil()
}
twitterで聞いてみたけどやはり大丈夫でない(このケースはサポートしてない)とのことでした